package com.reptile.init;


import com.alibaba.fastjson.JSON;
import com.common.kafka.DataPushApi;
import com.common.util.RedisUtil;
import com.reptile.constant.YsReptileConstant;
import com.reptile.dto.MaterialDTO;
import com.reptile.dto.NewsDTO;
import com.reptile.dto.ReptileDataDTO;
import com.reptile.entity.YsMaterial;
import com.reptile.service.YsMaterialService;
import com.reptile.service.YsNewsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 异步处理任务统一调度类
 *
 * @author songyafei
 */

@Slf4j
@Component
public class AsyncService {

    @Lazy
    @Resource
    private DataPushApi dataPushApi;

    @Resource
    private  YsMaterialService ysMaterialService;

    @Resource
    private YsNewsService ysNewsService;

    @Resource
    private  RedisUtil redisUtil;

    @Async("asyncServiceExecutor")
    public void sendNewsToData(List<NewsDTO> data){
        log.info("开始发送爬取的新闻信息到数据中心！");
        dataPushApi.sendNewsData(data);
        log.info("发送爬取的新闻信息结束！");
    }

    /**
     * 初始化素材信息
     * @return
     * @throws Exception
     */
    @Retryable(value = Exception.class,maxAttempts = 3,
            backoff = @Backoff(delay = 5000, multiplier = 1, maxDelay = 10000))
    public Boolean initYsMaterial() throws Exception {
        Long start = System.currentTimeMillis();
        log.info("查询初始化素材数据！");
        MaterialDTO materialDTO = MaterialDTO.builder().build();
        List<YsMaterial>  ysMaterialList = ysMaterialService.queryMaterial(materialDTO);
        if(CollectionUtils.isEmpty(ysMaterialList)){
            log.info("未查询到初始化素材数据，程序结束！");
            return false;
        }
        //去重处理
        Set<String> picUrls= ysMaterialList.stream()
                .map(YsMaterial::getMaterUrl)
                .collect(Collectors.toSet());
        //放入redis
        redisUtil.batchAdd(YsReptileConstant.PIC_REDIS_KEY, picUrls);
        //设置过期时间
        redisUtil.expire(YsReptileConstant.PIC_REDIS_KEY,999999,0);
        log.info("图片放入Redis成功");
        log.info("初始化素材数据结束！耗时{}",(System.currentTimeMillis()-start));
        return true;
    }

    /**
     * 初始化WallHaven 爬取的页数信息-缓存中不存在页数信息的时候
     */
    @Retryable(value = Exception.class,maxAttempts = 3,
            backoff = @Backoff(delay = 5000, multiplier = 1, maxDelay = 10000))
    public void initWallHavenPic(){
        if (!redisUtil.exists(YsReptileConstant.PIC_WALL_HAVEN_KEY)){
            ReptileDataDTO reptileDataDTO = ReptileDataDTO.builder()
                    .start(1).end(10)
                    .url(YsReptileConstant.WALL_HAVEN_PIC)
                    .errorUrl(null)
                    .build();
            redisUtil.sadd(YsReptileConstant.PIC_WALL_HAVEN_KEY, JSON.toJSONString(reptileDataDTO));
            //设置过期时间
            redisUtil.expire(YsReptileConstant.PIC_WALL_HAVEN_KEY,999999,0);
        }
        //设置过期时间
        redisUtil.expire(YsReptileConstant.PIC_WALL_HAVEN_KEY,999999,0);
    }

    /**
     * 清理图片、新闻重复数据
     */
    public void dataClearProcess() throws Exception {
        ysMaterialService.deleteRepeatData();
        ysNewsService.deleteRepeatData();
    }

    @Recover
    public void recover(Exception e) {
        System.out.println("重试机制执行完毕！");
    }
}
